home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v9n08.arc / TYPEFAST.ASM < prev    next >
Assembly Source File  |  1990-03-30  |  21KB  |  498 lines

  1. ;-----------------------------------------------;
  2. ;  TYPEFAST * PC Magazine * Michael J. Mefford  ;
  3. ;  Keyboard acceleration for XTs.               ;
  4. ;-----------------------------------------------;
  5.  
  6. BIOS_DATA      SEGMENT AT 40H
  7.                ORG     1AH
  8. BUFFER_HEAD    DW      ?
  9. BUFFER_TAIL    DW      ?
  10.                ORG     80H
  11. BUFFER_START   DW      ?
  12. BUFFER_END     DW      ?
  13. BIOS_DATA      ENDS
  14.  
  15. _TEXT          SEGMENT PUBLIC 'CODE'
  16.                ASSUME  CS:_TEXT
  17.                ORG     100H
  18. START:         JMP     INITIALIZE
  19.  
  20. ;              DATA AREA
  21. ;              ---------
  22. SIGNATURE      DB      CR,SPACE,SPACE,SPACE,CR,LF
  23. COPYRIGHT      DB      "TYPEFAST 1.0 (C) 1989 Ziff Communications Co.",CR,LF
  24. PROGRAMMER     DB      "PC Magazine ",BOX," Michael J. Mefford",CR,LF,LF,"$"
  25.                DB      CTRL_Z
  26.  
  27. CR             EQU     13
  28. LF             EQU     10
  29. CTRL_Z         EQU     26
  30. SPACE          EQU     32
  31. BOX            EQU     254
  32. BELL           EQU     7
  33.  
  34. TRUE           EQU     1
  35. FALSE          EQU     0
  36.  
  37. PORT_A         EQU     60H
  38. BREAK_CODE     EQU     80H
  39.  
  40. INITIAL_MAX    EQU     3
  41. REPEAT_MAX     EQU     31
  42.  
  43. BIOS_INT_9     DW      ?,?
  44. BIOS_INT_8     DW      ?,?
  45. SCAN_CHAR      DW      -1
  46. SCAN_CODE      DB      ?
  47. INIT_DEFAULT   EQU     INITIAL_MAX
  48. INIT_DELAY     DB      ?
  49. DELAY          DB      ?
  50. REPEAT_DEFAULT EQU     2
  51. REPEAT         DW      ?
  52. REPEAT_CNT     DW      ?
  53. REPEAT_FLAG    DB      FALSE
  54. ACTIVE_FLAG    DB      TRUE
  55. TYPEMATIC      DB      FALSE
  56.  
  57.  
  58. ;              CODE AREA
  59. ;              ---------
  60.  
  61. FASTKEY_INT_9  PROC    NEAR
  62.  
  63.                ASSUME  DS:NOTHING
  64.  
  65.                PUSH    AX                      ;Preserve some registers.
  66.                PUSH    BX
  67.                PUSH    DS
  68.  
  69.                IN      AL,PORT_A               ;Retrieve scan code.
  70.  
  71.                MOV     TYPEMATIC,FALSE         ;No typematic while processing.
  72.  
  73.                ASSUME  DS:BIOS_DATA            ;Point to BIOS data segment.
  74.                MOV     BX,SEG BIOS_DATA
  75.                MOV     DS,BX
  76.                MOV     BX,BUFFER_TAIL          ;Retrieve KBD buffer tail.
  77.  
  78.                PUSHF                           ;Emulate an interrupt.
  79.                CALL    DWORD PTR BIOS_INT_9    ;Let INT 9 process keystroke.
  80.  
  81.                CMP     ACTIVE_FLAG,TRUE        ;Are we active?
  82.                JNZ     INT_9_EXIT              ;If no, done here.
  83.  
  84.                CMP     BX,BUFFER_TAIL          ;Did buffer tail change?
  85.                JNZ     KEY_PRESS               ;If yes, process input.
  86.  
  87. ;------------------------------------------------------------------------;
  88. ; Clear the keyboard buffer if key is released and we've been repeating. ;
  89. ;------------------------------------------------------------------------;
  90.  
  91.                TEST    AL,BREAK_CODE           ;Else, was it a key release?
  92.                JZ      END_TYPEMATIC           ;If no, shift key;
  93.  
  94.                AND     AL,NOT BREAK_CODE       ;Else, strip release bit.
  95.                CMP     AL,SCAN_CODE            ;Is it same as last press?
  96.                JNZ     INT_9_EXIT              ;If no, done here.
  97.  
  98. END_TYPEMATIC: MOV     SCAN_CHAR,-1            ;Else, reset our scan/char code.
  99.  
  100.                CMP     REPEAT_FLAG,TRUE        ;Have we been stuffing?
  101.                JNZ     INT_9_EXIT              ;If no, done here.
  102.  
  103.                MOV     REPEAT_FLAG,FALSE       ;Else, reset repeat flag.
  104.                MOV     BUFFER_HEAD,BX          ;Clear keyboard buffer.
  105.                JMP     SHORT INT_9_EXIT        ;Exit.
  106.  
  107. ;----------------------------------------------------------------;
  108. ; If key press and same key then continue typematic, else reset. ;
  109. ;----------------------------------------------------------------;
  110.  
  111. KEY_PRESS:     MOV     SCAN_CODE,AL            ;Store the scan code.
  112.                MOV     AX,[BX]                 ;Retrieve last scan code.
  113.                CMP     AX,SCAN_CHAR            ;Is it the same as last?
  114.                MOV     SCAN_CHAR,AX            ;Store the character.
  115.                JZ      TYPEMATIC_ON            ;If yes, continue typematic.
  116.  
  117.                MOV     BL,INIT_DELAY           ;Else, reset the delay.
  118.                SHL     BL,1
  119.                SHL     BL,1
  120.                ADD     BL,4
  121.                MOV     DELAY,BL
  122.  
  123. TYPEMATIC_ON:  MOV     TYPEMATIC,TRUE          ;Turn typematic back on.
  124.  
  125. ;------------------------;
  126.  
  127. INT_9_EXIT:    POP     DS                      ;Restore registers.
  128.                POP     BX
  129.                POP     AX
  130.                IRET
  131.  
  132. FASTKEY_INT_9  ENDP
  133.  
  134. ;**********************************************;
  135.  
  136. FASTKEY_INT_8  PROC    NEAR
  137.  
  138.                PUSH    DS                      ;Preserve data segment.
  139.  
  140.                ASSUME  DS:_TEXT                ;Point to our data.
  141.                PUSH    CS
  142.                POP     DS
  143.  
  144.                CMP     TYPEMATIC,TRUE          ;Is typematic active?
  145.                JNZ     INT_8_EXIT              ;If no, done here.
  146.  
  147.                CMP     DELAY,0                 ;Is delay timed-out?
  148.                JZ      CK_BUFFER               ;If yes, see if we should stuff.
  149.  
  150.                DEC     DELAY                   ;Else, decrement delay.
  151.                JMP     SHORT INT_8_EXIT        ;Exit.
  152.  
  153. ;-----------------------------------------------------------;
  154. ; If there is room, stuff the keyboard with last keystroke. ;
  155. ;-----------------------------------------------------------;
  156.  
  157. CK_BUFFER:     STI
  158.                PUSH    AX                      ;Preserve some more registers.
  159.                PUSH    BX
  160.                PUSH    CX
  161.                PUSH    DI
  162.  
  163.                MOV     AX,SCAN_CHAR            ;Retrieve last scan/char code.
  164.                MOV     CX,REPEAT_CNT           ;Retrieve no. of times to repeat.
  165.                ASSUME  DS:BIOS_DATA            ;Point to BIOS data area.
  166.                MOV     BX,SEG BIOS_DATA
  167.                MOV     DS,BX
  168.                CLI                             ;No interrupts.
  169.  
  170. NEXT_STUFF:    ROL     CS:REPEAT,1             ;Rotate left one.
  171.                JNC     CK_REPEAT
  172.  
  173. STUFF_KBD:     MOV     BX,BUFFER_TAIL          ;Retrieve buffer tail.
  174.                MOV     DI,BX                   ;Move into DI.
  175.                INC     DI                      ;Point to next storage.
  176.                INC     DI
  177.                CMP     DI,BUFFER_END           ;Did we pass end of buffer?
  178.                JNZ     CK_FULL_KBD             ;If no, continue.
  179.                MOV     DI,BUFFER_START         ;Else, move to buffer start.
  180.  
  181. CK_FULL_KBD:   CMP     DI,BUFFER_HEAD          ;Is the buffer full?
  182.                JZ      CK_REPEAT               ;If is, skip.
  183.                MOV     [BX],AX                 ;Else, stuff buffer repeat.
  184.                MOV     BUFFER_TAIL,DI          ;Move the tail up one.
  185.  
  186.                MOV     CS:REPEAT_FLAG,TRUE     ;Flag that we stuffed buffer.
  187.  
  188. CK_REPEAT:     DEC     CX                      ;If no, continue until done.
  189.                JNS     NEXT_STUFF
  190.  
  191. FULL_KBD_EXIT: STI
  192.                POP     DI                      ;Restore registers.
  193.                POP     CX
  194.                POP     BX
  195.                POP     AX
  196.  
  197. INT_8_EXIT:    POP     DS
  198.                ASSUME  DS:NOTHING
  199.                JMP     DWORD PTR BIOS_INT_8    ;Give the old timer its turn.
  200.  
  201. FASTKEY_INT_8  ENDP
  202.  
  203. END_RESIDENT   LABEL   BYTE
  204.  
  205. ;**********************************************;
  206.  
  207. ;              DISPOSABLE DATA
  208. ;              ---------------
  209.  
  210. PATTERNS       DW      0000000000000000B, 1000000000000000B, 1000000010000000B
  211.                DW      1000010000100000B, 1000100010001000B, 1001001001001000B
  212.                DW      1001001001001001B, 1001001010010101B, 1010101010101010B
  213.                DW      1101010101010101B, 1101101011011010B, 1101101101101101B
  214.                DW      1110111011101110B, 1111011110111101B, 1111111011111110B
  215.                DW      1111111111111110B
  216.  
  217. SYNTAX         DB      "Syntax:  TYPEFAST [m][,n] | [/U] | [N]",CR,LF
  218.                DB      "m = typematic rate (0 - 31); larger m = faster rate"
  219.                DB      CR,LF
  220.                DB      "n = initial delay  (0 - 3); larger n = longer delay"
  221.                DB      CR,LF
  222.                DB      "default: m = 2; n = 3",CR,LF
  223.                DB      "N = Normal",CR,LF
  224.                DB      "/U = Uninstall",CR,LF,"$"
  225.  
  226. BAD_PARAMETER  DB      "Invalid parameter",CR,LF,LF,BELL,"$"
  227. UNLOAD_MSG     DB      "TYPEFAST can't be uninstalled.",CR,LF,BELL
  228.                DB      "Uninstall resident programs in reverse order.",CR,LF
  229.                DB      "TYPEFAST "
  230. INACTIVE_MSG   DB      "INACTIVE",CR,LF,LF,"$"
  231.  
  232. ALLOCATE_MSG   DB      "Memory allocation error",CR,LF,BELL,"$"
  233. INSTALL_MSG    DB      "Installed",CR,LF,LF,"$"
  234. UNINSTALL_MSG  DB      "Uninstalled",CR,LF,LF,"$"
  235.  
  236. ;--------------------------------------------------------------------;
  237. ; Search memory for a copy of our code, to see if already installed. ;
  238. ;--------------------------------------------------------------------;
  239.  
  240. INITIALIZE     PROC    NEAR
  241.  
  242.                ASSUME  DS:_TEXT
  243.                CLD                             ;All string operations forward.
  244.  
  245.                MOV     BX,OFFSET START         ;Point to start of code.
  246.                NOT     BYTE PTR [BX]           ;Change a byte so no false match
  247.                                                ; with a disk cache copy.
  248.                MOV     AX,CS                   ;Store our segment in AX.
  249.                MOV     DX,AX                   ;Start at our segment.
  250.  
  251. NEXT_PARA:     INC     DX                      ;Next paragraph.
  252.                MOV     ES,DX
  253.                CMP     DX,AX                   ;Is it our segment?
  254.                JZ      PARSE                   ;If yes, search is done.
  255.  
  256.                MOV     SI,BX                   ;Else, point to our signature.
  257.                MOV     DI,BX                   ; and offset of possible match.
  258.                MOV     CX,16                   ;Check 16 bytes for match.
  259.                REP     CMPSB
  260.                JNZ     NEXT_PARA               ;If no match, keep looking.
  261.  
  262. ;-------------------------------------------------;
  263. ; Parse the command line for uninstall parameter. ;
  264. ;-------------------------------------------------;
  265.  
  266. PARSE:         MOV     DX,OFFSET SIGNATURE     ;Display our signature.
  267.                CALL    PRINT_STRING
  268.  
  269.                MOV     SI,81H                  ;Point to command line.
  270. SEARCH_SWITCH: LODSB                           ;Get a byte.
  271.                CMP     AL,CR                   ;Is it carriage return?
  272.                JZ      PARAMETERS              ;If yes, done here.
  273.                CMP     AL,"/"                  ;Is there a switch character?
  274.                JNZ     SEARCH_SWITCH           ;If no, keep looking.
  275.                LODSB                           ;Else, get the switch character.
  276.                AND     AL,5FH                  ;Capitalize.
  277.                CMP     AL,"U"                  ;Is it uninstall?
  278.                JNZ     PARAMETERS              ;If no, done here.
  279.                JMP     UNINSTALL               ;Else, uninstall.
  280.  
  281. ;--------------------------------------------------------;
  282. ; Parse command line for typematic and delay parameters. ;
  283. ;--------------------------------------------------------;
  284.  
  285. PARAMETERS:    MOV     SI,81H                  ;Point to command line.
  286. FIND_PARA:     LODSB
  287.                CMP     AL,CR
  288.                JZ      FOUND_PARA
  289.                CMP     AL,SPACE
  290.                JBE     FIND_PARA
  291. FOUND_PARA:    DEC     SI
  292.                MOV     AL,[SI]
  293.                AND     AL,5FH
  294.                CMP     AL,"N"
  295.                MOV     AL,0
  296.                JZ      CALC_PATTERN
  297.                CALL    DECIMAL_INPUT           ;Get requested typematic rate.
  298.                MOV     AL,REPEAT_DEFAULT       ;Assume no parameter.
  299.                JCXZ    CALC_PATTERN            ;If none, use default.
  300.                MOV     AL,BL                   ;Else, rate in AL.
  301.                CMP     BL,REPEAT_MAX           ;Is it greater than max rate?
  302.                JA      ERROR_EXIT              ;If yes, exit with error msg.
  303.  
  304. CALC_PATTERN:  MOV     BL,AL
  305.                MOV     CL,4
  306.                SHR     BL,CL
  307.                XOR     BH,BH
  308.                MOV     ES:REPEAT_CNT,BX
  309.                AND     AL,0FH
  310.                XOR     AH,AH
  311.                SHL     AX,1
  312.                PUSH    SI
  313.                MOV     SI,AX
  314.                ADD     SI,OFFSET PATTERNS
  315.                LODSW
  316.                MOV     ES:REPEAT,AX
  317.                POP     SI
  318.  
  319. GET_DELAY:     CALL    DECIMAL_INPUT           ;Get requested initial delay.
  320.                MOV     AL,INIT_DEFAULT         ;Assume no parameter.
  321.                JCXZ    STORE_DELAY             ;If none, use default.
  322.                MOV     AL,BL                   ;Else, delay in AL.
  323.                CMP     BL,INITIAL_MAX          ;Is it greater than max delay?
  324.                JA      ERROR_EXIT              ;If yes, exit with error msg.
  325.  
  326. STORE_DELAY:   MOV     ES:INIT_DELAY,AL        ;Else, store initial delay.
  327.  
  328. ;-----------------------;
  329. ; Print active message. ;
  330. ;-----------------------;
  331.  
  332. CK_INSTALL:    MOV     ES:ACTIVE_FLAG,TRUE          ;Flag as active.
  333.                MOV     DX,OFFSET INACTIVE_MSG + 2   ;Display active msg.
  334.                CALL    PRINT_STRING
  335.                MOV     AX,ES                        ;Are we already installed?
  336.                MOV     BX,CS
  337.                CMP     AX,BX
  338.                JZ      INSTALL                      ;If no, install.
  339.                XOR     AL,AL                        ;Else, ERRORLEVEL of zero.
  340.                JMP     SHORT EXIT                   ;Exit.
  341.  
  342. ;-------------------------------------------------------------------;
  343. ; Exit.  Return ERRORLEVEL code 0 if successful, 1 if unsuccessful. ;
  344. ;-------------------------------------------------------------------;
  345.  
  346. ERROR_EXIT:    MOV     DX,OFFSET BAD_PARAMETER ;Display error message.
  347. MSG_EXIT:      CALL    PRINT_STRING
  348.                MOV     AL,1                    ;ERRORLEVEL = 1.
  349.  
  350. EXIT:          PUSH    AX                      ;Preserve ERRORLEVEL.
  351.                MOV     DX,OFFSET SYNTAX        ;Display syntax message.
  352.                CALL    PRINT_STRING
  353.                POP     AX                      ;Retrieve ERRORLEVEL.
  354.                MOV     AH,4CH                  ;Terminate.
  355.                INT     21H
  356.  
  357. ;--------------------------------;
  358. ; This is the install procedure. ;
  359. ;--------------------------------;
  360.  
  361. INSTALL:       MOV     AX,DS:[2CH]             ;Get environment segment.
  362.                MOV     ES,AX
  363.                MOV     AH,49H                  ;Free up environment.
  364.                INT     21H
  365.                MOV     DX,OFFSET ALLOCATE_MSG
  366.                JC      MSG_EXIT                ;If error, exit with message.
  367.  
  368.                MOV     AX,3509H                ;Get keyboard interrupt.
  369.                INT     21H
  370.                MOV     BIOS_INT_9[0],BX        ;Save old interrupt.
  371.                MOV     BIOS_INT_9[2],ES
  372.  
  373.                MOV     DX,OFFSET FASTKEY_INT_9 ;Install new interrupt.
  374.                MOV     AX,2509H
  375.                INT     21H
  376.  
  377.                MOV     AX,3508H                ;Get timer interrupt.
  378.                INT     21H
  379.                MOV     BIOS_INT_8[0],BX        ;Save old interrupt.
  380.                MOV     BIOS_INT_8[2],ES
  381.  
  382.                MOV     DX,OFFSET FASTKEY_INT_8 ;Install new interrupt.
  383.                MOV     AX,2508H
  384.                INT     21H
  385.  
  386.                MOV     DX,OFFSET INSTALL_MSG   ;Display install message.
  387.                CALL    PRINT_STRING
  388.                MOV     DX,OFFSET SYNTAX        ;Display syntax.
  389.                CALL    PRINT_STRING
  390.  
  391.                MOV     DX,OFFSET END_RESIDENT  ;Point to end of resident portion
  392.                ADD     DX,15                   ;Round up.
  393.                MOV     CL,4
  394.                SHR     DX,CL                   ;Convert to paragraphs.
  395.                MOV     AX,3100H                ;Return error code of zero.
  396.                INT     21H                     ;Terminate but stay resident.
  397.  
  398. ;---------------------------------------------------;
  399. ; This subroutine uninstalls the resident TYPEFAST. ;
  400. ;---------------------------------------------------;
  401.  
  402. UNINSTALL:     MOV     ES:ACTIVE_FLAG,FALSE    ;Flag as inactive.
  403.                MOV     ES:TYPEMATIC,FALSE      ;Turn off typematic.
  404.                MOV     DX,OFFSET UNLOAD_MSG    ;Error message if INT 9h changed.
  405.                MOV     CX,ES
  406.                MOV     BX,CS
  407.                CMP     AX,BX                   ;Is segment vector same?
  408.                JZ      UNINSTALL_END           ;If yes, not installed; exit.
  409.  
  410.                MOV     AX,3509H                ;Get keyboard interrupt.
  411.                INT     21H
  412.                CMP     BX,OFFSET FASTKEY_INT_9 ;Has it been hooked by another?
  413.                JNZ     UNINSTALL_END           ;If yes, exit with error message.
  414.                MOV     BX,ES
  415.                CMP     BX,CX                   ;Is the segment vector same?
  416.                JNZ     UNINSTALL_END           ;If yes, exit with error message.
  417.  
  418.                MOV     AX,3508H                ;Get timer interrupt.
  419.                INT     21H
  420.                CMP     BX,OFFSET FASTKEY_INT_8 ;Has it been hooked by another?
  421.                JNZ     UNINSTALL_END           ;If yes, exit with error message.
  422.                MOV     BX,ES
  423.                CMP     BX,CX                   ;Is the segment vector same?
  424.                JNZ     UNINSTALL_END           ;If yes, exit with error message.
  425.  
  426.                MOV     AH,49H                  ;Return memory to system pool.
  427.                INT     21H
  428.                MOV     DX,OFFSET ALLOCATE_MSG
  429.                JC      UNINSTALL_END           ;Display message if problem.
  430.  
  431.                MOV     DX,ES:BIOS_INT_9[0]     ;Restore old INT 9.
  432.                MOV     DS,ES:BIOS_INT_9[2]
  433.                MOV     AX,2509H
  434.                INT     21H
  435.  
  436.                MOV     DX,ES:BIOS_INT_8[0]     ;Restore old INT 8.
  437.                MOV     DS,ES:BIOS_INT_8[2]
  438.                MOV     AX,2508H
  439.                INT     21H
  440.  
  441.                PUSH   CS
  442.                POP    DS                       ;Point to our data.
  443.                MOV    DX,OFFSET UNINSTALL_MSG  ;Display uninstall message.
  444. UNINSTALL_END: JMP    MSG_EXIT                 ;And exit.
  445.  
  446. INITIALIZE     ENDP
  447.  
  448. ;---------------------------------;
  449. ; INPUT                           ;
  450. ;   SI points to parameter start. ;
  451. ;                                 ;
  452. ; OUTPUT                          ;
  453. ;   BL = number.                  ;
  454. ;   CX = parameter length.        ;
  455. ;   BP preserved.                 ;
  456. ;---------------------------------;
  457.  
  458. DECIMAL_INPUT  PROC    NEAR
  459.  
  460.                XOR     BL,BL                   ;Start with zero as number.
  461.                XOR     CX,CX                   ;Parameter length zero.
  462.  
  463. LEADING_WHITE: LODSB                           ;Get a byte.
  464.                CMP     AL,CR                   ;Is it carriage return?
  465.                JZ      ADJUST_DEC              ;If yes, done here.
  466.                CMP     AL,SPACE                ;Is it leading white space?
  467.                JBE     LEADING_WHITE           ;If yes, parse off.
  468.  
  469. DECIMAL:       DEC     SI                      ;Adjust pointer.
  470. NEXT_DECIMAL:  LODSB                           ;Get a character.
  471.                CMP     AL,CR                   ;Is it carriage return?
  472.                JZ      ADJUST_DEC              ;If yes, done here.
  473.                SUB     AL,"0"                  ;ASCII to binary.
  474.                JC      END_DECIMAL             ;If not between 0 and 9, skip.
  475.                CMP     AL,9
  476.                JA      END_DECIMAL
  477.                XCHG    AL,BL                   ;Swap old and new number.
  478.                MOV     CL,10                   ;Shift to left by multiplying
  479.                MUL     CL                      ; last entry by ten.
  480.                JC      DECIMAL_ERROR           ;If carry, too big.
  481.                ADD     BL,AL                   ;Add new number and store in BL.
  482.                JNC     NEXT_DECIMAL            ;If not carry, next number.
  483. DECIMAL_ERROR: MOV     BL,-1                   ;Else, too big; return -1.
  484.  
  485. ADJUST_DEC:    DEC     SI                      ;Adjust pointer.
  486. END_DECIMAL:   RET
  487.  
  488. DECIMAL_INPUT  ENDP
  489.  
  490. ;--------------------------;
  491.  
  492. PRINT_STRING:  MOV     AH,9                    ;Print string via DOS.
  493.                INT     21H
  494.                RET
  495.  
  496. _TEXT          ENDS
  497.                END     START
  498.